package test.entry;

import  java. util. Date;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.JCommander.Builder;
import dm.ast.model.gen.ASTGenBase;
import dm.repository.DmIFunInfo;
import test.envset.GlobalState;
import test.envset.RunEnv;
import test.utility.SqlCollections;
import test.utility.Utility;
import test.workload.GenWorker;
import test.workload.ObserverWorker;
import test.workload.RunWorker;
 import test.workload.Worker;

public class Main {
    public static String VERSION = "DmSql Tool version 1.0 build 2023-11-16";
    public static String VERSION_DESC = "Demo for sql-generator and sql-runner, use bookshop samples";
    public static MainOptions options = new MainOptions();
    public static Date starttime = null;
    public static Date starttime1 = null;

    public static void showVersion() {
        System.out.println(Main.VERSION);
        System.out.println(Main.VERSION_DESC);
        starttime = new Date();
        System.out.println("[start:]" + RunEnv.dateFormatLog.format(starttime));
    }


//    args为命令行参数，使用JCommander库进行解析。若出现--help参数，则输出帮助信息。
//    接着，调用RunEnv.setRunEnv()方法设置运行环境，最后根据是否设置了随机数种子，决定生成SQL的线程数量。
    public static int initOptions(String... args) {
        int rc = 0;
        Builder commandBuilder = JCommander.newBuilder().addObject(options);
        JCommander jc = commandBuilder.programName("DmSql").build();
        jc.parse(args);
        if (options.isHelp()) {
            jc.usage();
            return 1;
        }
//环境变量信息
        RunEnv.setRunEnv(options.getConfigFile());
//        if (options.getRandomSeed() != -1) { //如果设置了随机数种子,那么仅能使用一个生成SQL的线程RunEnv. WORKERS = 1;
//        }
        rc = 0;
        return rc;
    }

//在程序启动前等待一段时间，以确保所有线程都已经启动
    public static void sleepBeforeStart() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e1) {
// TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

//    选择进行SQL生成或SQL执行
    public static void work() {
        if (options.getSqlFile() == null) {
            genModel();
        } else {
            runSqls();
        }
        starttime1=new Date();
        long date=starttime1.getTime()-starttime.getTime();
        System.out.println("执行时间是："+date);
    }

    //sql生成
    private static void genModel() {
        //    根据运行环境设置生成SQL的线程数量。
        int workerCNT = RunEnv.WORKERS;
        if (workerCNT < 1) {
            workerCNT = 1;
        }

        //    然后，创建观察线程和全局状态对象，设置日志前缀，等待一段时间后开始生成SQL语句。
        Thread[] workers = new Thread[workerCNT];
        ObserverWorker obs = new ObserverWorker(); //观察线程

        GlobalState globalState = new GlobalState(options);
        GlobalState.setLogPre(RunEnv.sqlDateFormat.format(starttime)); //设置日志前缀//ASTGenBase. init(globalState);

        sleepBeforeStart();

        //    生成SQL语句的工作线程实现为GenWorker类。
        //    将所有工作线程加入到观察线程中并启动所有线程，等待所有工作线程执行完毕后停止观察线程，并输出生成SQL语句的统计信息。
        Worker worker = new GenWorker(0, globalState);
        obs.addWorker(worker);
        GenWorker.setMaxBufferLog(workerCNT);
        workers[0] = new Thread(worker);
        for (int i = 1; i < workerCNT; i++) {
            GlobalState tmps = new GlobalState(options);
            Worker tmpw = new GenWorker(i, tmps);
            obs.addWorker(tmpw);
            workers[i] = new Thread(tmpw);
        }
        Thread mon = new Thread(obs);
        for (int i = 0; i < workerCNT; i++) {
            workers[i].start();
        }
        mon.start();
        for (Thread work : workers) { //判断所有线程是否已经停止
            try {
                work.join();
            } catch (InterruptedException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        mon.interrupt();
        GlobalState.taskFinished();
        obs.finish();
        obs.showInfo();
    }

    //sql运行
//    首先根据运行环境设置执行SQL的线程数量。
//    然后创建观察线程和全局状态对象，设置日志前缀，读取SQL语句文件并输出统计信息，等待一段时间后开始执行SQL语句。
//    执行SQL语句的工作线程实现为RunWorker类。
//    将所有工作线程加入到观察线程中并启动所有线程，等待所有工作线程执行完毕后停止观察线程，并输出执行SQL语句的统计信息。
    private static void runSqls() {
        int workerCNT = RunEnv.WORKERS;
        if (workerCNT < 1) {
            workerCNT = 1;
        }
        Thread[] workers = new Thread[workerCNT];
        ObserverWorker obs = new ObserverWorker();
        GlobalState globalState = new GlobalState(options);
        GlobalState.setLogPre(RunEnv.sqlDateFormat.format(starttime));

        SqlCollections sqls = new SqlCollections(options.getSqlFile());
        Utility.output("[SQL file:]" + options.getSqlFile());
        Utility.output("[SQL count:]" + sqls.getSqlCount());
        sleepBeforeStart();
        RunWorker.setSqlCollections(sqls);
        Worker worker = new RunWorker(0, globalState);
        obs.addWorker(worker);
        workers[0] = new Thread(worker);
        for (int i = 1; i < workerCNT; i++) {
            GlobalState tmps = new GlobalState(options);
            Worker tmpw = new RunWorker(i, tmps);
            obs.addWorker(tmpw);
            workers[i] = new Thread(tmpw);
        }
        Thread mon = new Thread(obs);
        for (int i = 0; i < workerCNT; i++) {
            workers[i].start();
        }
        mon.start();
        for (Thread work : workers) { //判断所有线程是否已经停止
            try {
                work.join();
            } catch (InterruptedException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        mon.interrupt();
        GlobalState.taskFinished();
        obs.finish();
        obs.showInfo();
    }

    public static void main(String[] args) {// TODO Auto-generated method stub
        Main.showVersion();
        if (initOptions(args) != 0) {
            System.exit(0);
        }
        work();
    }
}